﻿using AutoMapper;
using Max.PH5_2006.ShoppingSite.Domain;
using Max.PH5_2006.ShoppingSite.IRespository;
using Max.PH5_2006.ShoppingSite.IService;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;


namespace Max.PH5_2006.ShoppingSite.Service
{
    //将TInputDto 转为 TEntity   将api传过来的的dto转为实体，再将实体传到仓储
    //将TEntity转为TOuputDto 将仓储返回的实体数据转为输出实体dto,以便api使用

    public class BaseService<TEntity, TInputDto, TOuputDto> : IBaseService<TEntity, TInputDto, TOuputDto> where TEntity : class, new()
    {
        IBaseRespository<TEntity> _respository;
        IMapper _map;
        public BaseService(IBaseRespository<TEntity> respository, IMapper map)
        {
            _respository = respository;
            _map = map;
        }

        public int Add(TInputDto t)
        {
            //_map.Map(t, typeof(TInputDto), typeof(TEntity));

            TEntity tentity = _map.Map<TInputDto, TEntity>(t);  //Map<源数据类型，目标数据类型>(源数据)
            int result = _respository.Add(tentity);

            return result;
        }

        public List<TOuputDto> Query()
        {
            List<TEntity> list = _respository.Query().ToList();
            List<TOuputDto> result = _map.Map<List<TEntity>, List<TOuputDto>>(list);
            return result;
        }


        public int Delete(List<dynamic> ids)
        {
            int result = _respository.Delete(ids);
            return result;
        }


        public List<TOuputDto> Query(Expression<Func<TEntity, bool>> where)
        {
            var list = _respository.Query(); //所有数据            
            list = list.Where(where); //根据表达式树进行查询
            //var result = _map.Map<List<TEntity>, List<TOuputDto>>(list); //数据映射
            var result = _map.Map<List<TOuputDto>>(list);
            return result;
            
        }
        //Func<string, bool> a1 = te;
        
        //Func<string, bool> a2 = (b) => { return b == "a"; };
        //private static bool te(string b)
        //{
        //    return b == "a";
        //}

        public List<TOuputDto> Query(Expression<Func<TEntity, bool>> where, int pageIndex, int pageSize,out int count)
        {
            #region 有几个条件，手动添加
            //Expression<Func<MemberEntity, bool>> whereExpression = null;
            //whereExpression = (p => p.Name.Equals("aa") && p.Password.Equals("")); //根据名称和密码查
            #endregion

            #region 手动拼接表达式

            ////定义一个表达式对象参数
            //ParameterExpression pe = Expression.Parameter(typeof(TEntity));

            ////表达式内容
            ////构建一个表达式(左边表达  + 右边表达)
            ////=> x.Name == "aaa"
            ////=> x.Name是左边，"aaa"是右边
            ////最后左边和右边合并
            //var left = Expression.Property(pe, typeof(TEntity).GetProperty("Name"));
            //var right = Expression.Constant("aaa");
            //var ea = Expression.Equal(left, right);

            //Expression<Func<TEntity, bool>> expression = t => true;

            //{
            //    //如果有多个条件，重复上面即可,
            //    //...
            //    //然后合并多个条件
            //    //var eas = Expression.AndAlso(ea1, ea2);

            //    //最后将ea转换为我们需要的条件表达式委托
            //    expression = Expression.Lambda<Func<TEntity, bool>>(ea, pe);
            //}
            #endregion

            #region 封装的一个表达式

            //Common.QueryExpressionCollection queries = new Common.QueryExpressionCollection();
            //queries.Add(new Common.Query { Name = "Name", Operator = Common.Query.Operators.Equal, Value = "aa" });
            //queries.AsExpression<TEntity>();

            #endregion

            var list = _respository.Query(); //所有数据            
            list = list.Where(where); //根据表达式树进行查询
            
            count = list.Count();  //查询后的结果总条数

            var result = _map.Map<List<TEntity>, List<TOuputDto>>(list.ToList()); //数据映射
            result = result.Skip((pageIndex-1)*pageSize).Take(pageSize).ToList();

            return result;
        }

        public List<TOuputDto> Query<TKey>(Expression<Func<TEntity, bool>> where, 
            Expression<Func<TEntity,TKey>> order,bool isAsc, int pageIndex, int pageSize, out int count)
        {
            var list = _respository.Query();        
            list = list.Where(where); 

            if(isAsc)
            {
                list = list.OrderBy(order);//list.OrderBy(x => x.Name); //
            }
            else
            {
                list = list.OrderByDescending(order);
            }

            count = list.Count(); 

            var result = _map.Map<List<TEntity>, List<TOuputDto>>(list.ToList()); 
            result = result.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();

            return result;
        }

        public TOuputDto QueryById(string id)
        {
            var t = _respository.QueryById(id);
            var result = _map.Map<TEntity,TOuputDto>(t);
            return result;
        }

        public int Update(TInputDto t)
        {
            TEntity entity = _map.Map<TInputDto, TEntity>(t);

            int result = _respository.Update(entity);
            return result;
        }
    }

}
